﻿#-------------------------------------------------------------------------------
# Name:        Monsters
# Purpose:     All monsters are here
#
# Author:      Lorien
#
# Created:     01.09.2011
# Copyright:   (c) Lorien 2011
# Licence:     Private
#-------------------------------------------------------------------------------
#!/usr/bin/env python

import pygame
from consts import *
from gobject import GObject
from utils import postUserEvent

#Monster base class
class MonsterBase(GObject):
    #Game-space monster w and h
    width = 1
    height = 1

    def __init__(self, position:tuple, map_worker):
        GObject.__init__(self, position, map_worker)

        #Walking system
        self.last_cost = self.map_worker.map_matrix[self.x][self.y]

        if not self.map_worker.map_objects[self.x][self.y]:
            self.map_worker.map_objects[self.x][self.y] = self

        self.map_worker.map_matrix[self.x][self.y] = -3
        self.reached = True
        self.target = (self.x, self.y)
        self.direction = (0, 0)
        self.alive = True

    def update(self, time_pass):

        if self.reached:
            map_matrix = self.map_worker.map_matrix

            if map_matrix[self.x][self.y] != -3 and self.last_cost == -3:
                self.last_cost = map_matrix[self.x][self.y]
                self.map_worker.map_objects[self.x][self.y] = self
                map_matrix[self.x][self.y] = -3

            if map_matrix[self.x][self.y] == -3 and self.last_cost == -3:
                return

            if self.last_cost == -3:
                return

            last_cost = self.last_cost

            if self.y + 1 < self.map_worker.height:
                if (map_matrix[self.x][self.y + 1]) > self.last_cost and map_matrix[self.x][
                            self.y + 1] - self.last_cost < 100:
                    self.target = (self.x, self.y + 1)
                    self.last_cost = self.map_worker.map_matrix[self.target[0]][self.target[1]]
                    self.direction = (0, 1)
                    self.reached = False

            if self.x + 1 < self.map_worker.width:
                if (map_matrix[self.x + 1][self.y]) > self.last_cost and map_matrix[self.x + 1][
                    self.y] - self.last_cost < 100:
                    self.target = (self.x + 1, self.y)
                    self.last_cost = self.map_worker.map_matrix[self.target[0]][self.target[1]]
                    self.direction = (1, 0)
                    self.reached = False

            if self.y - 1 >= 0:
                if (map_matrix[self.x][self.y - 1]) > self.last_cost and map_matrix[self.x][
                            self.y - 1] - self.last_cost < 100:
                    self.target = (self.x, self.y - 1)
                    self.last_cost = self.map_worker.map_matrix[self.target[0]][self.target[1]]
                    self.direction = (0, -1)
                self.reached = False

            if self.x - 1 >= 0:
                if (map_matrix[self.x - 1][self.y]) > self.last_cost and map_matrix[self.x - 1][
                    self.y] - self.last_cost < 100:
                    self.target = (self.x - 1, self.y)
                    self.last_cost = self.map_worker.map_matrix[self.target[0]][self.target[1]]
                    self.direction = (-1, 0)
                    self.reached = False

            if not self.reached and not self.map_worker.map_objects[self.target[0]][self.target[1]]:
                self.map_worker.map_matrix[self.target[0]][self.target[1]] = -3
                self.map_worker.map_matrix[self.x][self.y] = last_cost

                self.map_worker.map_objects[self.target[0]][self.target[1]] = self
                self.map_worker.map_objects[self.x][self.y] = False

        if not self.reached:
            d = self.speed * time_pass / 1000.0

            old = (self.x, self.y)
            new = (self.x + d * self.direction[0], self.y + d * self.direction[1])

            if (old[0] <= self.target[0] <= new[0] or old[0] >= self.target[0] >= new[0]) \
                and (old[1] <= self.target[1] <= new[1] or old[1] >= self.target[1] >= new[1]):
                self.x = self.target[0]
                self.y = self.target[1]
                self.reached = True
                self.direction = (0, 0)
            else:
                self.x += d * self.direction[0]
                self.y += d * self.direction[1]

            if (self.x, self.y) in self.map_worker.aim_points:
                self.map_worker.map_matrix[self.x][self.y] = self.last_cost
                self.kill()
                postUserEvent(EVENT_GAME_OVER) # game over!

    def kill(self):
        if self.alive:
            pygame.sprite.Sprite.kill(self)

            if self.last_cost == -3:
                return

            self.map_worker.map_matrix[self.target[0]][self.target[1]] = self.last_cost
            self.map_worker.map_objects[self.target[0]][self.target[1]] = False

            # Tell about death
            postUserEvent(EVENT_KILL_MONSTER, monster=self)

            self.alive = False

    def isMonster(self):
        return True

    def isAlive(self):
        return self.alive

    def receiveDamage(self, damage):
        self.health -= damage
        if self.health <= 0:
            self.kill()


class MonsterFabric:
    def create(id, position, map_worker):
        d = {1: MonsterMarioStar,
             2: MonsterMarioFlower,
             3: MonsterMarioGoomba,
             4: MonsterMarioTroopa,
             5: MonsterMarioParatroopa,
             6: MonsterMarioCheep,
             7: MonsterMarioChukolator,
             8: MonsterMarioBlooper,
             9: MonsterMarioLuvbi,
             10: MonsterMarioLakity
        }

        return d[id](position, map_worker)

#Test monster!!!
class MonsterMan(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/star.png')

        self.cost = 2
        self.speed = 3
        self.type = MONSTERGROUND


#id:1
class MonsterMarioStar(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/star.png')

        self.health = 1
        self.speed = 2
        self.cost = 1
        self.type = MONSTERGROUND


#id:2
class MonsterMarioFlower(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/flower.png')

        self.health = 3
        self.speed = 3
        self.cost = 3
        self.type = MONSTERGROUND


#id:3
class MonsterMarioGoomba(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/goomba.png')

        self.health = 10
        self.speed = 2
        self.cost = 5
        self.type = MONSTERGROUND


#id:4
class MonsterMarioTroopa(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/koopa_troopa.png')

        self.health = 5
        self.speed = 5
        self.cost = 5
        self.type = MONSTERGROUND


#id:5
class MonsterMarioParatroopa(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/koopa_paratroopa.png')

        self.health = 4
        self.speed = 4
        self.cost = 5
        self.type = MONSTERAIR


#id:6
class MonsterMarioCheep(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/cheep.png')

        self.health = 7
        self.speed = 4
        self.cost = 8
        self.type = MONSTERGROUND


#id:7
class MonsterMarioChukolator(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/chukolator.png')

        self.health = 15
        self.speed = 2
        self.cost = 8
        self.type = MONSTERGROUND


#id:8
class MonsterMarioBlooper(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/blooper.png')

        self.health = 10
        self.speed = 3
        self.cost = 8
        self.type = MONSTERGROUND


#id:9
class MonsterMarioLuvbi(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/luvbi.png')

        self.health = 8
        self.speed = 5
        self.cost = 10
        self.type = MONSTERGROUND


#id:10
class MonsterMarioLakity(MonsterBase):
    def __init__(self, position:tuple, map_worker):
        #Initing
        MonsterBase.__init__(self, position, map_worker)

        #Graphics
        self.loadGraphics('mario/lakity.png')

        self.health = 8
        self.speed = 4
        self.cost = 10
        self.type = MONSTERAIR

